<?php
App::uses('AppController', 'Controller');
/**
 * Users Controller
 *
 * @property User $User
 */
class UsersController extends AppController {

	public $uses = array('User', 'TemplateFlownode', 'Application');
	
	public function beforeFilter() {
		//TODO 'preventing unlogin users' might don't work
		parent::beforeFilter();
		$this->Auth->allow('add', 'logout');
	}
/**
 * index method
 *
 * @return void
 */
	public function index() {
		$this->User->recursive = 0;
		$this->set('users', $this->paginate());
	}

/**
 * view method
 *
 * @param string $id
 * @return void
 */
	public function view($id = null) {
		$this->User->id = $id;
		if (!$this->User->exists()) {
			throw new NotFoundException(__('Invalid user'));
		}
		$this->set('user', $this->User->read(null, $id));
	}

/**
 * add method
 *
 * @return void
 */
	public function add() {
		if ($this->request->is('post')) {
			$this->User->create();
			if ($this->User->save($this->request->data)) {
				$this->Session->setFlash(__('The user has been saved'));
				$this->redirect(array('action' => 'index'));
			} else {
				$this->Session->setFlash(__('The user could not be saved. Please, try again.'));
			}
		}
	}

/**
 * edit method
 *
 * @param string $id
 * @return void
 */
	public function edit($id = null) {
		$this->User->id = $id;
		if (!$this->User->exists()) {
			throw new NotFoundException(__('Invalid user'));
		}
		if ($this->request->is('post') || $this->request->is('put')) {
			if ($this->User->save($this->request->data)) {
				$this->Session->setFlash(__('The user has been saved'));
				$this->redirect(array('action' => 'index'));
			} else {
				$this->Session->setFlash(__('The user could not be saved. Please, try again.'));
			}
		} else {
			$this->request->data = $this->User->read(null, $id);
		}
	}

/**
 * delete method
 *
 * @param string $id
 * @return void
 */
	public function delete($id = null) {
		if (!$this->request->is('post')) {
			throw new MethodNotAllowedException();
		}
		$this->User->id = $id;
		if (!$this->User->exists()) {
			throw new NotFoundException(__('Invalid user'));
		}
		if ($this->User->delete()) {
			$this->Session->setFlash(__('User deleted'));
			$this->redirect(array('action' => 'index'));
		}
		$this->Session->setFlash(__('User was not deleted'));
		$this->redirect(array('action' => 'index'));
	}
	
	public function login() {
		if ($this->request->is('post')) {
			if ($this->Auth->login()) {
				$this->redirect($this->Auth->redirect());
			} else {
				$this->Session->setFlash(__('Invalid username or password, try again'));
			}
		}
	}
	
	public function logout() {
		$this->redirect($this->Auth->logout());
	}
	
	private function __getUserId($text) {
		if (strpos($text, "@") != False) {
			CakeLog::write('debug', $text . " email");
			$user =  $this -> User -> findByEmail($text);
			if (!$user)
				return False;
			else
				return $user['User']['id'];
				
		} else {
			CakeLog::write('debug', $text . " id");
			$user = $this -> User -> findById($text);
			if (!$user)
				return False;
			else
				return $user['User']['id'];
		}
	}
	
	public function addApplication() {
		if ($this -> request -> is('post')) {
			$post_data = array();
			$post_data['ApplicationFlownode'] = array();
			$post_user_size = 0;
			$post_tag_size = 0;
			$post_tags = array();
			$post_consist = True;
			$has_template = False;
			$template_list = array();
			
			for ($post_user_size = 0; isset($this -> data[ 'user' . ($post_user_size + 1) ]); $post_user_size++) {
				if (!$this -> data[ 'user' . ($post_user_size + 1)]) {
					break;
				}
				if ($this -> __getUserId($this -> data[ 'user' . ($post_user_size + 1) ])) {
					array_push($post_data['ApplicationFlownode'], array(
							'user_id' => $this -> __getUserId($this -> data[ 'user' . ($post_user_size + 1) ]),
							'loc_index' => $post_user_size + 1,
							'loc_identity' => 1,
							'status' => 0
						)
					);
				} else {
					$this->Session->setFlash(__('Cannot find user #%s.', $this -> data[ 'user' . ($post_user_size + 1) ]));
					$this->redirect(array('action' => 'addApplication'));
				}
			}
			
			for ($post_tag_size = 0; isset($this -> data[ 'tag' . ($post_tag_size + 1) ]['key']); $post_tag_size++) {
				if (!$this -> data[ 'tag' . ($post_tag_size + 1) ]['key']) {
					continue;
				}
				$post_tags[$this -> data[ 'tag' . ($post_tag_size + 1) ]['key']] = $this -> data[ 'tag' . ($post_tag_size + 1) ]['value'];
			}
			
			
			if (isset($this->data['template_id']) && is_numeric($this->data['template_id']) && is_int((int)$this->data['template_id'])) {
				$template = $this->TemplateFlownode->findAllByTemplateId($this->data['template_id']); 
				if (!$template) {
					$this->Session->setFlash(__('Cannot find template #%s.', $this -> data['template_id']));
					$this->redirect(array('action' => 'addApplication'));
				}
				$hasTemplate = True;
				if (sizeof($template) != $post_user_size) {
					$post_consist = False;
				} else {
					for ($k = 0; $k < $post_user_size; $k++) {
						if (!$template) {
							$post_consist = False;
							break;
						}
						if ($post_data['ApplicationFlownode'][$k]['user_id'] != $template[$k]['TemplateFlownode']['user_id']) {
							$post_consist = False;
							break;
						}
						if ($post_data['ApplicationFlownode'][$k]['loc_index'] != $template[$k]['TemplateFlownode']['loc_index']) {
							$post_consist = False;
							break;
						}
						if ($post_data['ApplicationFlownode'][$k]['loc_identity'] != $template[$k]['TemplateFlownode']['loc_identity']) {
							$post_consist = False;
							break;
						}
					}
				}
				//check template consistency
			} else {
				$hasTemplate = False;
			}	
			$post_data['Application'] = array(
				'user_id' => $this -> Auth -> User('id'),
				'template_id' => ($hasTemplate && $post_consist) ? $this -> data['template_id'] : 0,
				'title' => $this -> data['title'],
				'final_status' => $post_user_size + 1,
				'postscript' => $this -> data['postscript'],
				'status' => 1,
				'tags' => json_encode($post_tags)
			);
			
			if ($this -> Application -> saveAssociated($post_data, array('deep' => true))) {
				$this->Session->setFlash('An Application has been added successfully.');
			} else {
				$this->Session->setFlash('The Application could not be saved.');
				$this->redirect(array('action' => 'index'));
			}
			$this -> set('template_list', $template_list);
		} else {
			$template_list = array();
			
		}
		
	}

/**
 * add template method(all flownode included)
 * @return void
 */

	//TODO assert: A user won't appear in the same Flownode.loc_index with 2 or above different Flownode.loc_identity
	public function addTemplate() {
		if ($this->request->is('post')) {
			$final_status = 0;

			foreach ($this->data['TemplateFlownode'] as $flownode) {
				$final_status = $final_status < $flownode['loc_index'] ? $flownode['loc_index'] : $final_status;
			}

			$this->User->Application->create();
			$this->request->data['TemplateFlownode']['user_id'] = $this->Auth->user('id');
			$this->request->data['Template']['final_status'] = $final_status;

			//TODO might elide parameters for saveAssociated
			if ($this->User->Application->saveAssociated()) {
				$this->Session->setFlash("A template has been added successfully");
			} else {
				return false;
			}
		}
	}

/**
 * save application || template to a new template
 * post
 * @return void
 */
	public function saveToTemplate() {
	}

	/**
	 * get all the applications submitted&not finished by current user
	 *
	 * @return void
	 */

	// status == 0 => 'application is denied'
	// status < final_status => 'application is waiting to be approved'
	// status == final_status => 'application is approved'

	public function getWaitingApprovedApplications() {
		$this->User->Application->recursive = 0;
		//TODO limit 20 page
		$applicationsBySubmitter = $this->paginate("Application",
			array(
				'Application.user_id' => $this->Auth->User('id'),
				'AND' => array(
					'`Application.status` < `Application.final_status`',
					'`Application.status` > 0'
				)
			)
		);
		$this->set('applicationsBySubmitter', $applicationsBySubmitter);
	}

	/**
	 * get the approval progress of specified application_id
	 * int application_id by post
	 * @return void
	 */
	//TODO syntax will be wrong
	public function getApplicationApprovalProgress($application_id) {
		if (!$this->request->is('post')) {
			throw new MethodNotAllowedException();
		}
		$approvalProgress = $this->User->Application->find('all', 
			array(
				'conditions' => array(
					'Application.id' => $application_id,
					'Application.user_id' => $this->Auth->User('id'),
					'Flownode.status' => '1',
					'Flownode.loc_index <' => 'Applications.status'
				)
			)
		);
		$this->set('approvalProgress', $approvalProgress);
	}

/**
 * get all the flownodes with applications which shall be approved/disapproved by current user
 *
 * @return void
 */
	public function getPendingApprovedFlownodes() {
		$this->User->ApplicationFlownode->recursive = 0;
		$rawFlownodesByApprover = $this->User->ApplicationFlownode->find('all', 
			array(
				'conditions' => array(
					'ApplicationFlownode.user_id' => $this->Auth->User('id'),
				)
			)
		);

		$flownodesByApprover = array();
		foreach($rawFlownodesByApprover as $flownode) {
			if ($flownode["ApplicationFlownode"]["loc_index"] == $flownode["Application"]["status"]) {
				$flownodesByApprover[] = $flownode;
			}
		}

		$this->set('flownodesByApprover', $flownodesByApprover);
	}
	
/**
 * approve a flownode 
 *
 * @return void
 */
	
	public function approveFlownode($id = null) {
		if (!$this->request->is('post')) {
			throw new MethodNotAllowedException();
		}
		$this->User->ApplicationFlownode->recursive = 0;
		$this->User->ApplicationFlownode->id = $id;
		if ($this->User->ApplicationFlownode->exists()) {
			$flownode = $this->User->ApplicationFlownode->read(null, $id);
			if ($flownode['Application']['status'] == $flownode['ApplicationFlownode']['loc_index']) {
				$flownode['ApplicationFlownode']['status'] = '1';
				$parallelFlownode = $this->User->ApplicationFlownode->find('all', 
					array(
						'conditions' => array(
							'loc_index' => $flownode['ApplicationFlownode']['loc_index'],
							'ApplicationFlownode.status' => '0',
							'NOT' => array(
								'loc_identity' => $flownode['ApplicationFlownode']['loc_identity']
							)
						)
					));	
				if (!$parallelFlownode) {
					 ++$flownode['Application']['status']; //next stage
				}
				var_dump($flownode);
				//$this->User->ApplicationFlownode->saveAssociated($flownode);
				//$this->redirect(array('controller' => 'users', 'action' => 'getPendingApprovedFlownodes'));
			} else {
				//status has already been skipped
			}
		} else {
			throw new NotFoundException(__('Invalid application'));
		}
	}
	
	public function isAuthorized($user) {
		if ($this->action == 'getPendingApprovedFlownodes' 
			|| $this->action == 'addApplication' 
			|| $this->action == 'addTemplate') {
			return true;
		}
        return parent::isAuthorized($user);
    }
}
